﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Messaging;
using Soa32.Zanfranceschi.Comum.Modelo;
using Soa32.Zanfranceschi.Mensageria.Mensagens;

namespace Soa32.Zanfranceschi.Cliente
{
	internal static class MensageriaCliente
	{
		internal static void RequestReply(int chamadas)
		{
			MessageQueue filaRequisicao = new MessageQueue(@".\private$\requisicao");
			MessageQueue filaResposta = new MessageQueue(@".\private$\resposta");
			MessagePropertyFilter filtro = new MessagePropertyFilter();
			filtro.SetDefaults();

			filaRequisicao.MessageReadPropertyFilter = filtro;
			filaResposta.MessageReadPropertyFilter = filtro;
			filaResposta.Formatter = new BinaryMessageFormatter();

			AsyncCallback receberMensagem = new AsyncCallback(r => 
			{ 
				Resposta resposta = (Resposta)filaResposta.EndReceive(r).Body; 
			});

			IList<TimeSpan> tempos = new List<TimeSpan>();
			DateTime inicioTotal = DateTime.Now;
			for (int i = 0; i < chamadas; i++)
			{
				DateTime inicio = DateTime.Now;
				Requisicao requisicao = new Requisicao("requisição");
				Message mensagemRequisicao = new Message(requisicao, new BinaryMessageFormatter());
				mensagemRequisicao.ResponseQueue = filaResposta;
				filaRequisicao.Send(mensagemRequisicao);
				filaResposta.BeginReceive(TimeSpan.FromSeconds(2), mensagemRequisicao.CorrelationId, receberMensagem);
				tempos.Add(DateTime.Now - inicio);
			}
			TimeSpan duracao = DateTime.Now - inicioTotal;
			Console.WriteLine("Mensageria Request/Reply. Resultados para {0} chamadas:", chamadas);
			Console.WriteLine("Tempo médio: {0}ms", TimeSpan.FromTicks(Convert.ToInt64(tempos.Average(t => t.Ticks))).TotalMilliseconds);
			Console.WriteLine("Tempo total: {0}ms", duracao.TotalMilliseconds);
		}
		internal static void Command(int chamadas)
		{
			MessageQueue filaComando = new MessageQueue(@".\private$\comando");
			MessagePropertyFilter filtro = new MessagePropertyFilter();
			filtro.SetDefaults();
			filaComando.MessageReadPropertyFilter = filtro;

			IList<TimeSpan> tempos = new List<TimeSpan>();
			DateTime inicioTotal = DateTime.Now;
			for (int i = 0; i < chamadas; i++)
			{
				DateTime inicio = DateTime.Now;
				Comando comando = new Comando(Entidade.Nova(), "comando");
				Message mensagemComando = new Message(comando, new BinaryMessageFormatter());
				filaComando.Send(mensagemComando);
				tempos.Add(DateTime.Now - inicio);
			}
			TimeSpan duracao = DateTime.Now - inicioTotal;
			Console.WriteLine("Mensageria Command. Resultados para {0} chamadas:", chamadas);
			Console.WriteLine("Tempo médio: {0}ms", TimeSpan.FromTicks(Convert.ToInt64(tempos.Average(t => t.Ticks))).TotalMilliseconds);
			Console.WriteLine("Tempo total: {0}ms", duracao.TotalMilliseconds);
		}
		internal static void Sub()
		{
			string subscriberQueuePath = @".\private$\notificacao";
			MessageQueue subscribeQueue = new MessageQueue(subscriberQueuePath);
			subscribeQueue.MulticastAddress = "236.1.1.1:8001";
			subscribeQueue.Formatter = new BinaryMessageFormatter();
			Console.WriteLine("Aguardando notificações...");
			while (true)
			{
				Message notificationMessage = subscribeQueue.Receive();
				Notificacao notificacao = (Notificacao)notificationMessage.Body;
				Console.WriteLine("{0} - Notificação recebida: {1}", DateTime.Now, notificacao.Texto);
			}
		}
	}
}